﻿#include "testtemplatewidget.h"
#include "ui_testtemplatewidget.h"
#include "model/datamanager.h"
#include <QMessageBox>
#include <QScopedValueRollback>
#include <QtDebug>
#include "subbandtablemodel.h"
#include "common/common.h"
#include <cmath>
#include <common/calcutils.h>

/**
 * @brief TestTemplateWidget::TestTemplateWidget
 * @details 构造测试模板页面并初始化界面组件。
 * @param parent Qt 父级窗口。
 */
TestTemplateWidget::TestTemplateWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::TestTemplateWidget)
{
    ui->setupUi(this);

    initTableView();
    //加载数据
    initEditors();
    initListView();
    ui->ch_VSWR->hide();
    ui->doubleSpinBox_Smax->hide();
    ui->doubleSpinBox_Smin->hide();
    ui->co_VSWR->hide();
    ui->co_VSWRXmodel->hide();
    ui->co_VSWRYmodel->hide();
}

/**
 * @brief TestTemplateWidget::~TestTemplateWidget
 * @details 释放界面资源。
 */
TestTemplateWidget::~TestTemplateWidget()
{
    delete ui;
}

/**
 * @brief TestTemplateWidget::initTableView
 * @details 初始化子区间表格视图与模型。
 */
void TestTemplateWidget::initTableView()
{
    // 声明数据模型
    m_subModel = new SubBandTableModel();
    // 绑定模型与显示界面
    ui->tableView->setModel(m_subModel);
    // 设置表格属性
    ui->tableView->verticalHeader()->setVisible(false);                 // 隐藏默认序号列
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 整行选中
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);  // 内容不可编辑
    ui->tableView->setShowGrid(false);                                  //设置不显示格子线
    ui->tableView->horizontalHeader()->setDefaultSectionSize(120);      // 设置初始列宽
    ui->tableView->horizontalHeader()->setStretchLastSection(true);     // 将最后一列设置为自动扩展
    ui->tableView->setAlternatingRowColors(true);                       // 启用交替行颜色，方便阅读
    ui->tableView->setColumnHidden(13, true);                           //隐藏调制模式
    connect(ui->tableView->selectionModel(), &QItemSelectionModel::currentChanged,
            this, &TestTemplateWidget::onTableCurrentChanged);
}

/**
 * @brief TestTemplateWidget::on_btn_add_subTemplate_clicked
 * @details 添加新的测试子区间并同步界面。
 */
void TestTemplateWidget::on_btn_add_subTemplate_clicked()
{
    if (!m_currentTpl)
        return;

    // 上一个子区间的 stop 作为新子区间的 start
    double start = 80e6;
    if (!m_currentTpl->subBands.isEmpty()) {
        const auto &last = m_currentTpl->subBands.back();
        if (last)
            start = last->stopFreq; // 相邻重复一个点（允许）
    }

    auto sb = QSharedPointer<TestSubBand>::create();
    // 创建默认子区间对象
    sb->hardwareTemplateID = 0;
    sb->startFreq = start;
    sb->stopFreq = start + 100e6;
    sb->stepSize = 10e6;
    sb->stepMode = AxisScale::Linear;
    sb->dwellTime = 100.0;
    sb->freqPlan = FrequencyPlanType::SweepLinear;
    sb->freqTableID = 0;
    sb->immunityLevelType = ImmunityLevelType::Fixed;
    sb->immunityLevelValue = 10.0;
    sb->upperTolerance = 0.0;
    sb->lowerTolerance = 0.0;
    sb->generatorModulation = GeneratorModulationType::Off;
    sb->plumWidth = 500;   //us
    sb->plumPeriod = 1000; //us

    // 追加到“当前模板”和“表模型”（使用同一指针实例，保持一致）
    m_currentTpl->subBands.push_back(sb);
    m_subModel->appendExisting(sb);

    // 选中新行并滚动
    const int newRow = m_subModel->rowCount() - 1;
    const QModelIndex idx = m_subModel->index(newRow, 0);
    ui->tableView->setCurrentIndex(idx);
    ui->tableView->scrollTo(idx);

    // 同步到编辑控件
    loadRowToEditors(newRow);
}

/**
 * @brief TestTemplateWidget::on_btn_del_subTemplate_clicked
 * @details 删除选中的测试子区间。
 */
void TestTemplateWidget::on_btn_del_subTemplate_clicked()
{
    if (!m_currentTpl)
        return;
    auto sel = ui->tableView->selectionModel();
    if (!sel)
        return;

    QModelIndexList rows = sel->selectedRows();
    if (rows.isEmpty())
        return;

    // 从大到小删除
    std::sort(rows.begin(), rows.end(), [](const QModelIndex &a, const QModelIndex &b) { return a.row() > b.row(); });

    for (const auto &ix : rows) {
        const int r = ix.row();
        if (r >= 0 && r < m_currentTpl->subBands.size())
            m_currentTpl->subBands.removeAt(r);
        m_subModel->removeRow(r);
    }

    // 更新当前选择
    if (m_subModel->rowCount() > 0) {
        const int r = std::min(rows.last().row(), m_subModel->rowCount() - 1);
        const QModelIndex idx = m_subModel->index(r, 0);
        ui->tableView->setCurrentIndex(idx);
    } else {
        setEditorsEnabled(false);
    }
}

/**
 * @brief TestTemplateWidget::initListView
 * @details 初始化模板列表视图及其数据源。
 */
void TestTemplateWidget::initListView()
{
    m_modelTemplateList = new QStringListModel(this);
    ui->listView->setModel(m_modelTemplateList);
    ui->listView->setEditTriggers(QAbstractItemView::DoubleClicked);

    m_overviews = DataManager::instance()->getTestTemplateOverviews().toVector();
    QStringList names;
    names.reserve(m_overviews.size());
    for (const auto &ov : m_overviews)
        names << ov.name;
    m_modelTemplateList->setStringList(names);
    // 绑定“当前项变化”信号（注意：必须先 setModel 再取 selectionModel）
    connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged,
            this, &TestTemplateWidget::onListCurrentChanged);

    // 选中首项并触发一次加载
    if (!m_overviews.isEmpty()) {
        const QModelIndex first = m_modelTemplateList->index(0);
        ui->listView->setCurrentIndex(first);
    }
}

/**
 * @brief TestTemplateWidget::initEditors
 * @details 初始化右侧编辑控件并绑定信号。
 */
void TestTemplateWidget::initEditors()
{
    //硬件模板数据更新，刷新对应UI
    auto dm = DataManager::instance();
    connect(dm, &DataManager::sig_hardwareTemplatesChanged,
            this, &TestTemplateWidget::slot_hardwareTemplatesChanged);
    connect(dm, &DataManager::sig_parameterTablesChanged,
            this, &TestTemplateWidget::slot_parameterTablesChanged);

    ui->cBox_levelmode->clear();
    ui->cBox_levelmode->addItem(tr("SubstitutionMethod"), static_cast<int>(LevelModeType::SubstitutionMethod));
    ui->cBox_levelmode->addItem(tr("Sensor"), static_cast<int>(LevelModeType::Sensor));
    ui->cBox_powerControl->clear();
    ui->cBox_powerControl->addItem(tr("Generator_Level"), static_cast<int>(PowerMeasurementType::Generator_Level));
    ui->cBox_powerControl->addItem(tr("Forwrd_Power"), static_cast<int>(PowerMeasurementType::Forwrd_Power));
    //    ui->cBox_powerControl->addItem("Net_Power", static_cast<int>(PowerMeasurementType::Net_Power));

    // 频率表 / 极值表 / 频率计划 / 抗扰来源 / 调制
    const auto paramOVs = DataManager::instance()->getParameterTableOverviews();
    ui->comboBox_freqTable->clear();
    ui->comboBox_immunityTable->clear();
    ui->comboBox_calTable->clear();
    ui->comboBox_calTable->addItem(STR_NO_TABLE, 0);
    for (const auto &ov : paramOVs) {
        if (ov.type == ParamTableKind::Frequency) {
            ui->comboBox_freqTable->addItem(ov.name, ov.id);
        } else if (ov.type == ParamTableKind::LimitLine) {
            ui->comboBox_immunityTable->addItem(ov.name, ov.id);
        } else if (ov.type == ParamTableKind::Cal) {
            ui->comboBox_calTable->addItem(ov.name, ov.id);
        }
    }

    ui->comboBox_frequencyPlan->clear();
    ui->comboBox_frequencyPlan->addItem(tr("SweepLinear"), static_cast<int>(FrequencyPlanType::SweepLinear));
    ui->comboBox_frequencyPlan->addItem(tr("FreqTableOnly"), static_cast<int>(FrequencyPlanType::FreqTableOnly));
    ui->comboBox_frequencyPlan->addItem(tr("FreqTable+Step"), static_cast<int>(FrequencyPlanType::FreqTablePlusStep));

    ui->comboBox_stepMode->clear();
    ui->comboBox_stepMode->addItem(tr("LIN"), static_cast<int>(AxisScale::Linear));
    ui->comboBox_stepMode->addItem(tr("LOG"), static_cast<int>(AxisScale::Logarithmic));

    ui->comboBox_generatorModulation->clear();
    ui->comboBox_generatorModulation->addItem("OFF", static_cast<int>(GeneratorModulationType::Off));
    //    ui->comboBox_generatorModulation->addItem("AM", static_cast<int>(GeneratorModulationType::AM));
    //    ui->comboBox_generatorModulation->addItem("FM", static_cast<int>(GeneratorModulationType::FM));
    ui->comboBox_generatorModulation->addItem("PM", static_cast<int>(GeneratorModulationType::PM));
    ui->cBox_measurementCategory->clear();
    ui->cBox_measurementCategory->addItem(tr("EMS Radiated"), static_cast<int>(HardwareTemplateType::RS));
    ui->cBox_measurementCategory->addItem(tr("EMS Conducted"), static_cast<int>(HardwareTemplateType::CS));

    // 连接编辑控件的信号（统一回到 onEditorChanged）
    auto conIdx = QOverload<int>::of(&QComboBox::currentIndexChanged);

    connect(ui->comboBox_frequencyPlan, conIdx, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->comboBox_hwTemplate, conIdx, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->comboBox_generatorModulation, conIdx, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->comboBox_freqTable, conIdx, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->comboBox_immunityTable, conIdx, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->comboBox_stepMode, conIdx, this, &TestTemplateWidget::onEditorChanged);

    //    auto conDbl = QOverload<double>::of(&QDoubleSpinBox::valueChanged);
    auto conDbl = QOverload<>::of(&QDoubleSpinBox::editingFinished);
    connect(ui->doubleSpinBox_startF, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_stopF, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_stepsize, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_dwelltime, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_immunityValue, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_levelup, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_levledown, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_plumPeriod, conDbl, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->doubleSpinBox_plumWidth, conDbl, this, &TestTemplateWidget::onEditorChanged);

    auto btnToggled = QOverload<bool>::of(&QAbstractButton::toggled); //(bool checked)
    connect(ui->radioButton_immunityTable, btnToggled, this, &TestTemplateWidget::onEditorChanged);
    connect(ui->radioButton_immunityValue, btnToggled, this, &TestTemplateWidget::onEditorChanged);

    setEditorsEnabled(false); // 初始不可编辑，等选中行后启用
}

/**
 * @brief TestTemplateWidget::loadRowToEditors
 * @details 将指定行的子区间数据加载到编辑控件。
 * @param row 表格行索引。
 */
void TestTemplateWidget::loadRowToEditors(int row)
{
    const auto sb = m_subModel->rowPtr(row);
    if (!sb) {
        setEditorsEnabled(false);
        return;
    }
    double prevStop = 0.0;
    if (row > 0) {
        const auto prev = m_subModel->rowPtr(row - 1);
        if (prev)
            prevStop = prev->stopFreq;
    }

    QSignalBlocker b1(ui->doubleSpinBox_startF);
    QSignalBlocker b2(ui->doubleSpinBox_stopF);

    ui->doubleSpinBox_startF->setMinimum(prevStop / 1e6); // 仅防重叠

    ui->doubleSpinBox_startF->setValue(sb->startFreq / 1e6);
    ui->doubleSpinBox_stopF->setMinimum(ui->doubleSpinBox_startF->value()); // stop > start 的动态下限
    ui->doubleSpinBox_stopF->setValue(sb->stopFreq / 1e6);

    QScopedValueRollback<bool> guard(m_blockEditorSignals, true); // 屏蔽 onEditorChanged

    ui->comboBox_stepMode->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_stepMode, static_cast<int>(sb->stepMode)));
    if (sb->stepMode == AxisScale::Linear) {
        ui->doubleSpinBox_stepsize->setValue(sb->stepSize / 1e6);
        ui->label_stepUnit->setText("MHz");
    } else {
        ui->doubleSpinBox_stepsize->setValue(sb->stepSize);
        ui->label_stepUnit->setText("%");
    }
    unsigned long long freqCount = CalcUtils::calculateFrequencyPoints(sb->startFreq, sb->stopFreq, sb->stepSize, sb->stepMode);
    ui->lineEdit_points->setText(QString::number(freqCount));

    ui->doubleSpinBox_dwelltime->setValue(sb->dwellTime / 1000);

    ui->comboBox_frequencyPlan->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_frequencyPlan, static_cast<int>(sb->freqPlan)));
    ui->comboBox_hwTemplate->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_hwTemplate, sb->hardwareTemplateID));
    ui->comboBox_freqTable->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_freqTable, sb->freqTableID));

    if (sb->immunityLevelType == ImmunityLevelType::Fixed) {
        ui->comboBox_immunityTable->setEnabled(false);
        ui->radioButton_immunityValue->setChecked(true);
        ui->doubleSpinBox_immunityValue->setEnabled(true);
        ui->doubleSpinBox_immunityValue->setValue(sb->immunityLevelValue);
    } else {
        ui->doubleSpinBox_immunityValue->setEnabled(false);
        ui->radioButton_immunityTable->setChecked(true);
        ui->comboBox_immunityTable->setEnabled(true);
        ui->comboBox_immunityTable->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_immunityTable, sb->immunityLevelTableID));
    }

    ui->doubleSpinBox_levelup->setValue(sb->upperTolerance);
    ui->doubleSpinBox_levledown->setValue(sb->lowerTolerance);
    ui->comboBox_generatorModulation->setCurrentIndex(Utils::findComboBoxIndexByData(ui->comboBox_generatorModulation, static_cast<int>(sb->generatorModulation)));
    ui->doubleSpinBox_plumPeriod->setValue(sb->plumPeriod);
    ui->doubleSpinBox_plumWidth->setValue(sb->plumWidth);
    ui->doubleSpinBox_plumPeriod->setEnabled(sb->generatorModulation != GeneratorModulationType::Off);
    ui->doubleSpinBox_plumWidth->setEnabled(sb->generatorModulation != GeneratorModulationType::Off);
}

/**
 * @brief TestTemplateWidget::applyEditorsToRow
 * @details 将编辑控件的数值回写到数据模型。
 * @param row 表格行索引。
 */
void TestTemplateWidget::applyEditorsToRow(int row)
{
    auto sb = m_subModel->rowPtr(row);
    if (!sb)
        return;

    // start 的最小值 = 上一个子区间的 stop（若 row==0，无下限）
    double prevStop = 0.0;
    if (row > 0) {
        const auto prev = m_subModel->rowPtr(row - 1);
        if (prev)
            prevStop = prev->stopFreq;
    }

    double startHz = ui->doubleSpinBox_startF->value() * 1e6;
    if (startHz < prevStop) {
        startHz = prevStop; // 防止重叠
        QSignalBlocker b(ui->doubleSpinBox_startF);
        ui->doubleSpinBox_startF->setValue(startHz / 1e6);
        qWarning() << "ui->doubleSpinBox_startF <= prevStop";
    }

    double stopHz = ui->doubleSpinBox_stopF->value() * 1e6;
    if (stopHz <= startHz) {
        // stopHz = startHz + std::max(1.0, sb->stepSize); // 确保严格大于
        stopHz = startHz + 100; // 确保严格大于
        QSignalBlocker b(ui->doubleSpinBox_stopF);
        ui->doubleSpinBox_stopF->setValue(stopHz / 1e6);
        qWarning() << "ui->doubleSpinBox_stopF <= ui->doubleSpinBox_startF";
    }
    ui->doubleSpinBox_stopF->setMinimum(ui->doubleSpinBox_startF->value());

    sb->stepMode = static_cast<AxisScale>(ui->comboBox_stepMode->currentIndex());
    (sb->stepMode == AxisScale::Linear) ? ui->label_stepUnit->setText("MHz") : ui->label_stepUnit->setText("%");

    sb->startFreq = startHz;
    sb->stopFreq = stopHz;

    if (sb->stepMode == AxisScale::Linear) {
        sb->stepSize = ui->doubleSpinBox_stepsize->value() * 1e6;
    } else {
        sb->stepSize = ui->doubleSpinBox_stepsize->value();
    }
    unsigned long long freqCount = CalcUtils::calculateFrequencyPoints(sb->startFreq, sb->stopFreq, sb->stepSize, sb->stepMode);
    ui->lineEdit_points->setText(QString::number(freqCount));

    m_subModel->notifyRowChanged(row);

    sb->dwellTime = ui->doubleSpinBox_dwelltime->value() * 1000;

    sb->freqPlan = static_cast<FrequencyPlanType>(ui->comboBox_frequencyPlan->currentIndex());
    (sb->freqPlan == FrequencyPlanType::SweepLinear) ? ui->comboBox_freqTable->setEnabled(false)
                                                     : ui->comboBox_freqTable->setEnabled(true);
    sb->hardwareTemplateID = ui->comboBox_hwTemplate->currentData().toInt();
    sb->freqTableID = ui->comboBox_freqTable->currentData().toInt();

    bool isFixed = (ui->radioButton_immunityValue->isChecked()) ? true : false;
    (isFixed) ? sb->immunityLevelType = ImmunityLevelType::Fixed : sb->immunityLevelType = ImmunityLevelType::Table;
    ui->tBtn_synchronize->setEnabled(isFixed);
    ui->doubleSpinBox_immunityValue->setEnabled(isFixed);
    ui->comboBox_immunityTable->setEnabled(!isFixed);

    sb->immunityLevelTableID = ui->comboBox_immunityTable->currentData().toInt();
    sb->immunityLevelValue = ui->doubleSpinBox_immunityValue->value();

    sb->upperTolerance = ui->doubleSpinBox_levelup->value();
    sb->lowerTolerance = ui->doubleSpinBox_levledown->value();
    sb->generatorModulation = static_cast<GeneratorModulationType>(ui->comboBox_generatorModulation->currentData().toInt());
    if(ui->doubleSpinBox_plumPeriod->value() > ui->doubleSpinBox_plumWidth->value()){
        sb->plumPeriod = ui->doubleSpinBox_plumPeriod->value();
        sb->plumWidth = ui->doubleSpinBox_plumWidth->value();
    }    else{
        ui->doubleSpinBox_plumPeriod->setValue(sb->plumPeriod);
        ui->doubleSpinBox_plumWidth->setValue(sb->plumWidth);
    }
    m_subModel->notifyRowChanged(row);

    ui->doubleSpinBox_plumPeriod->setEnabled(sb->generatorModulation != GeneratorModulationType::Off);
    ui->doubleSpinBox_plumWidth->setEnabled(sb->generatorModulation != GeneratorModulationType::Off);

    ui->co_GeneratorXmodel->setCurrentIndex(static_cast<int>(sb->stepMode));
    ui->co_ImmunityLevelXmodel->setCurrentIndex(static_cast<int>(sb->stepMode));
    ui->co_AmplifierFPXmodel->setCurrentIndex(static_cast<int>(sb->stepMode));
    ui->co_AmplifierRPXmodel->setCurrentIndex(static_cast<int>(sb->stepMode));
    //    ui->co_VSWRXmodel->setCurrentIndex(static_cast<int>(sb->stepMode));
}

/**
 * @brief TestTemplateWidget::setEditorsEnabled
 * @details 启用或禁用右侧编辑区域。
 * @param en true 启用，false 禁用。
 */
void TestTemplateWidget::setEditorsEnabled(bool en)
{
    ui->groupBox_4->setEnabled(en);
    ui->groupBox_3->setEnabled(en);
}

/**
 * @brief TestTemplateWidget::refreshHwTemplateCommbox
 * @details 根据测量类别刷新硬件模板下拉框。
 * @param htType 当前测量类别。
 */
void TestTemplateWidget::refreshHwTemplateCommbox(const HardwareTemplateType htType)
{
    const auto allHwOVs = DataManager::instance()->getHardwareTemplateOverviews();
    int currentSelectedId = -1;
    if (ui->comboBox_hwTemplate->count() > 0) {
        // 使用 currentData 获取当前选中项关联的 ID
        QVariant currentData = ui->comboBox_hwTemplate->currentData();
        if (currentData.isValid()) {
            currentSelectedId = currentData.toInt();
        }
    }
    const QSignalBlocker blocker(ui->comboBox_hwTemplate);
    ui->comboBox_hwTemplate->clear();

    for (const auto &hwOv : allHwOVs) {
        HardwareTemplatePtr hwTemplate = DataManager::instance()->getFullHardwareTemplate(hwOv.id);
        if (hwTemplate && hwTemplate->type == htType) {
            ui->comboBox_hwTemplate->addItem(hwOv.name, hwOv.id);
        }
    }

    int indexToSelect = -1;
    if (currentSelectedId > 0) {
        indexToSelect = Utils::findComboBoxIndexByData(ui->comboBox_hwTemplate, currentSelectedId);
    }

    if (indexToSelect < 0 && ui->comboBox_hwTemplate->count() > 0) {
        indexToSelect = 0;
    }

    if (indexToSelect >= 0) {
        ui->comboBox_hwTemplate->setCurrentIndex(indexToSelect);
        onEditorChanged();
    } else {
        qWarning() << "No hardware templates found for type:" << static_cast<int>(htType);
    }
}

/**
 * @brief TestTemplateWidget::on_btn_add_testTemplate_clicked
 * @details 新建测试模板并追加到列表。
 */
void TestTemplateWidget::on_btn_add_testTemplate_clicked()
{
    TestTemplatePtr newTemplate;
    QString newTemplateName = "TestTemplate";
    const QModelIndex curIdx = ui->listView->currentIndex();
    if (curIdx.isValid()) {
        const int row = curIdx.row();
        if (row >= 0 && row < m_overviews.size()) {
            const OverviewItem ov = m_overviews.at(row);
            if (ov.id > 0) {
                newTemplate = DataManager::instance()->duplicateTestTemplate(ov.id);
                newTemplateName = newTemplate->name;
            }
        }
    }

    if (!newTemplate) {
        int counter = 1;
        QString originalName = newTemplateName;
        while (true) {
            bool isDuplicate = DataManager::instance()->overVivewNameExists(DataManager::instance()->getTestTemplateOverviews(), newTemplateName);
            if (!isDuplicate) {
                break;
            }
            newTemplateName = originalName + "(" + QString::number(counter++) + ")";
        }
        qDebug() << "Requesting DataManager to add new test template with name:" << newTemplateName;
        newTemplate = DataManager::instance()->addTestTemplate(newTemplateName);
    }

    if (!newTemplate) {
        qWarning() << "addTestTemplate failed";
        return;
    }
    OverviewItem ov;
    ov.id = newTemplate->id;
    ov.name = newTemplateName;
    m_overviews.push_back(ov);

    // 在模型的末尾插入一行
    const int newRow = m_modelTemplateList->rowCount();
    m_modelTemplateList->insertRow(newRow);
    m_modelTemplateList->setData(m_modelTemplateList->index(newRow), newTemplateName);

    // 获取新行的索引并设置数据
    const QModelIndex index = m_modelTemplateList->index(newRow);
    // 让新添加的项可见并被选中
    ui->listView->setCurrentIndex(index);
    onListCurrentChanged(index, QModelIndex());
}

/**
 * @brief TestTemplateWidget::on_btn_del_testTemplate_clicked
 * @details 删除当前选中的测试模板。
 */
void TestTemplateWidget::on_btn_del_testTemplate_clicked()
{
    //取当前选中的列表项
    const QModelIndex curIdx = ui->listView->currentIndex();
    if (!curIdx.isValid()) {
        QMessageBox::information(this, tr("提示"), tr("请先选择要删除的测试模板。"));
        return;
    }
    const int row = curIdx.row();
    if (row < 0 || row >= m_overviews.size()) {
        QMessageBox::warning(this, tr("错误"), tr("内部索引无效，无法删除。"));
        return;
    }

    const OverviewItem ov = m_overviews.at(row);
    if (ov.id <= 0) {
        QMessageBox::warning(this, tr("错误"), tr("无效的测试模板 ID。"));
        return;
    }

    // 提交任何可能未结束的编辑（避免丢失 UI 状态）
    if (QWidget *fw = QApplication::focusWidget())
        fw->clearFocus();

    //  调用数据层删除（数据库级联删除子区间）
    const bool ok = DataManager::instance()->removeTestTemplate(ov.id);
    if (!ok) {
        QMessageBox::critical(this, tr("删除失败"), tr("数据库删除失败，请查看日志。"));
        return;
    }

    // 如果删除的是当前加载的模板，清空右侧视图和编辑区
    if (m_currentTpl && m_currentTpl->id == ov.id) {
        m_currentTpl.reset();        // 清空当前模板
        m_subModel->setSubBands({}); // 清空子区间表
        setEditorsEnabled(false);    // 禁用编辑区
    }

    m_overviews.removeAt(row);
    m_modelTemplateList->removeRows(row, 1);

    //移动选择到合适的相邻项，并触发加载
    int newRow = row;
    const int rows = m_modelTemplateList->rowCount();
    if (newRow >= rows)
        newRow = rows - 1; // 若删除了最后一行，选择移到新的最后一行

    if (newRow >= 0) {
        const QModelIndex newIndex = m_modelTemplateList->index(newRow);
        ui->listView->setCurrentIndex(newIndex);
        onListCurrentChanged(newIndex, QModelIndex()); // 加载新的选中模板
    } else {
        // 列表空了，右侧保持清空状态
        setEditorsEnabled(false);
    }

    QMessageBox::information(this, tr("成功"), tr("测试模板已删除。"));
}

/**
 * @brief TestTemplateWidget::slot_templateNameChanged
 * @details 处理模板名称编辑后的模型更新通知。
 * @param topLeft 已更改区域的左上索引。
 * @param bottomRight 已更改区域的右下索引。
 */
void TestTemplateWidget::slot_templateNameChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    Q_UNUSED(bottomRight)

    if (!topLeft.isValid()) {
        return;
    }

    // 获取被修改的行号
    int row = topLeft.row();

    // 从模型中获取修改后的新文本
    QString newText = m_modelTemplateList->data(topLeft, Qt::DisplayRole).toString();
    qDebug() << "Item at row" << row << "changed to:" << newText;
}

/**
 * @brief TestTemplateWidget::on_cBox_levelunit_currentTextChanged
 * @details 统一更新场强单位显示。
 * @param arg1 当前选中的单位字符串。
 */
void TestTemplateWidget::on_cBox_levelunit_currentTextChanged(const QString &arg1)
{
    ui->label_ImmunityFieldUnit->setText(arg1);
    ui->co_ImmunityLevelUnit->setCurrentText(arg1);
}

//绑定listView,点击左侧模板列表时触发
/**
 * @brief TestTemplateWidget::onListCurrentChanged
 * @details 响应模板列表项变化并加载详细数据。
 * @param current 当前选中的索引。
 * @param previous 之前选中的索引。
 */
void TestTemplateWidget::onListCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
    if (!current.isValid())
        return;
    int row = current.row();
    if (row < 0 || row >= m_overviews.size())
        return;

    const OverviewItem &ov = m_overviews.at(row);
    if (ov.id <= 0) {
        qWarning() << "Invalid overview id at row" << row;
        return;
    }

    m_currentTpl = DataManager::instance()->getFullTestTemplate(ov.id);
    if (!m_currentTpl) {
        m_subModel->setSubBands({});
        setEditorsEnabled(false);
        return;
    }
    m_subModel->setSubBands(m_currentTpl->subBands);
    refreshHwTemplateCommbox(m_currentTpl->flowKind);

    // 默认选中第一行
    if (!m_currentTpl->subBands.isEmpty()) {
        const QModelIndex idx0 = m_subModel->index(0, 0);
        ui->tableView->setCurrentIndex(idx0);
        onTableCurrentChanged(idx0, QModelIndex());
    } else {
        setEditorsEnabled(false);
    }

    ui->cBox_measurementCategory->setCurrentIndex(ui->cBox_measurementCategory->findData(m_currentTpl->flowKind));
    ui->cBox_levelunit->setCurrentText(m_currentTpl->immunityLevelUnit);
    ui->doubleSpinBox_Impedance->setValue(m_currentTpl->impedance);
    ui->cBox_levelmode->setCurrentIndex(ui->cBox_levelmode->findData(m_currentTpl->levelMode));
    ui->cBox_powerControl->setCurrentIndex(ui->cBox_powerControl->findData(m_currentTpl->powerMeasurement));
    ui->comboBox_calTable->setCurrentIndex(ui->comboBox_calTable->findData(m_currentTpl->calibrationDataID));
    ui->radioButton_offset->setChecked(m_currentTpl->offsetCheck);
    ui->doubleSpinBox_offset->setValue(m_currentTpl->offset);

    ui->ch_GeneratorOutput->setChecked(m_currentTpl->CheckGeneratorOutput);
    ui->doubleSpinBox_Gmax->setValue(m_currentTpl->GeneratorOutputYmax);
    ui->doubleSpinBox_Gmin->setValue(m_currentTpl->GeneratorOutputYmin);
    ui->co_GeneratorXmodel->setCurrentIndex(static_cast<int>(m_currentTpl->GeneratorOutputXAxisScale));
    ui->co_GeneratorYmodel->setCurrentIndex(static_cast<int>(m_currentTpl->GeneratorOutputYAxisScale));

    ui->ch_AmplifierFP->setChecked(m_currentTpl->CheckAmplifierFP);
    ui->doubleSpinBox_AFmax->setValue(m_currentTpl->AmplifierFPYmax);
    ui->doubleSpinBox_AFmin->setValue(m_currentTpl->AmplifierFPYmin);
    ui->co_AmplifierFPXmodel->setCurrentIndex(static_cast<int>(m_currentTpl->AmplifierFPXAxisScale));
    ui->co_AmplifierFPYmodel->setCurrentIndex(static_cast<int>(m_currentTpl->AmplifierFPYAxisScale));

    ui->ch_AmplifierRP->setChecked(m_currentTpl->CheckAmplifierRP);
    ui->doubleSpinBox_ARmax->setValue(m_currentTpl->AmplifierRPYmax);
    ui->doubleSpinBox_ARmin->setValue(m_currentTpl->AmplifierRPYmin);
    ui->co_AmplifierRPXmodel->setCurrentIndex(static_cast<int>(m_currentTpl->AmplifierRPXAxisScale));
    ui->co_AmplifierRPYmodel->setCurrentIndex(static_cast<int>(m_currentTpl->AmplifierRPYAxisScale));

    ui->ch_VSWR->setChecked(m_currentTpl->CheckVSWR);
    ui->doubleSpinBox_Smax->setValue(m_currentTpl->VSWRYmax);
    ui->doubleSpinBox_Smin->setValue(m_currentTpl->VSWRYmin);
    ui->co_VSWRXmodel->setCurrentIndex(static_cast<int>(m_currentTpl->VSWRXAxisScale));
    ui->co_VSWRYmodel->setCurrentIndex(static_cast<int>(m_currentTpl->VSWRYAxisScale));

    ui->ch_ImmunityLevel->setChecked(m_currentTpl->CheckImmunityLevel);
    ui->doubleSpinBox_Imax->setValue(m_currentTpl->ImmunityLevelYmax);
    ui->doubleSpinBox_Imin->setValue(m_currentTpl->ImmunityLevelYmin);
    ui->co_ImmunityLevelXmodel->setCurrentIndex(static_cast<int>(m_currentTpl->ImmunityLevelXAxisScale));
    ui->co_ImmunityLevelYmodel->setCurrentIndex(static_cast<int>(m_currentTpl->ImmunityLevelYAxisScale));
    ui->co_ImmunityLevelUnit->setCurrentText(m_currentTpl->immunityLevelUnit);
}

/**
 * @brief TestTemplateWidget::onTableCurrentChanged
 * @details 表格行切换时同步编辑器内容。
 * @param current 当前索引。
 * @param previous 之前的索引。
 */
void TestTemplateWidget::onTableCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
    if (!current.isValid()) {
        setEditorsEnabled(false);
        return;
    }
    setEditorsEnabled(true);
    loadRowToEditors(current.row());
}

/**
 * @brief TestTemplateWidget::onEditorChanged
 * @details 统一处理编辑控件值变化并更新模型。
 */
void TestTemplateWidget::onEditorChanged()
{
    if (m_blockEditorSignals)
        return;
    const QModelIndex cur = ui->tableView->currentIndex();
    if (!cur.isValid())
        return;
    applyEditorsToRow(cur.row());
}

/**
 * @brief TestTemplateWidget::slot_hardwareTemplatesChanged
 * @details 当硬件模板数据变化时刷新下拉框。
 */
void TestTemplateWidget::slot_hardwareTemplatesChanged()
{
    if (m_currentTpl)
        refreshHwTemplateCommbox(m_currentTpl->flowKind);
}

/**
 * @brief TestTemplateWidget::slot_parameterTablesChanged
 * @details 当参数表数据变化时刷新相关选择框。
 */
void TestTemplateWidget::slot_parameterTablesChanged()
{
    // 记录当前选择以便恢复
    const int keepFreqId = ui->comboBox_freqTable->currentData().toInt();
    const int keepImmId = ui->comboBox_immunityTable->currentData().toInt();
    const int keepCalId = ui->comboBox_calTable->currentData().toInt();

    QSignalBlocker b1(ui->comboBox_freqTable);
    QSignalBlocker b2(ui->comboBox_immunityTable);
    QSignalBlocker b3(ui->comboBox_calTable);

    ui->comboBox_freqTable->clear();
    ui->comboBox_immunityTable->clear();
    ui->comboBox_calTable->clear();
    ui->comboBox_calTable->addItem(STR_NO_TABLE, 0);

    for (const auto &ov : DataManager::instance()->getParameterTableOverviews()) {
        if (ov.type == ParamTableKind::Frequency) {
            ui->comboBox_freqTable->addItem(ov.name, ov.id);
        } else if (ov.type == ParamTableKind::LimitLine) {
            ui->comboBox_immunityTable->addItem(ov.name, ov.id);
        } else if (ov.type == ParamTableKind::Cal) {
            ui->comboBox_calTable->addItem(ov.name, ov.id);
        }
    }

    // 恢复选择（如选项不存在则回退到第一个）
    auto restore = [](QComboBox *cb, int keepId) {
        const int ix = Utils::findComboBoxIndexByData(cb, keepId);
        cb->setCurrentIndex(ix >= 0 ? ix : (cb->count() > 0 ? 0 : -1));
    };
    restore(ui->comboBox_freqTable, keepFreqId);
    restore(ui->comboBox_immunityTable, keepImmId);
    restore(ui->comboBox_calTable, keepCalId);
}

/**
 * @brief TestTemplateWidget::on_btn_save_Template_clicked
 * @details 保存当前测试模板及子区间配置。
 */
void TestTemplateWidget::on_btn_save_Template_clicked()
{
    //必须有当前模板
    if (!m_currentTpl) {
        QMessageBox::warning(this, tr("提示"), tr("未选择测试模板"));
        return;
    }

    // 提交任何未提交的编辑（SpinBox/ComboBox 等）
    if (QWidget *fw = QApplication::focusWidget())
        fw->clearFocus();

    const QModelIndex curRowIdx = ui->tableView->currentIndex();
    if (curRowIdx.isValid()) {
        applyEditorsToRow(curRowIdx.row());
    }

    //  从列表读取模板名并回写
    const QModelIndex listIdx = ui->listView->currentIndex();
    if (listIdx.isValid()) {
        const QString name = m_modelTemplateList->data(listIdx, Qt::DisplayRole).toString().trimmed();
        if (name.isEmpty()) {
            QMessageBox::warning(this, tr("提示"), tr("模板名称不能为空"));
            return;
        }
        m_currentTpl->name = name;
    }

    // 如果界面上尚有其它模板级控件（levelMode/powerMeasurement/unit/impedance 等）
    m_currentTpl->immunityLevelUnit = ui->cBox_levelunit->currentText();
    m_currentTpl->impedance = ui->doubleSpinBox_Impedance->value();
    m_currentTpl->levelMode = static_cast<LevelModeType>(ui->cBox_levelmode->currentData().toInt());
    m_currentTpl->powerMeasurement = static_cast<PowerMeasurementType>(ui->cBox_powerControl->currentData().toInt());
    m_currentTpl->calibrationDataID = ui->comboBox_calTable->currentData().toInt();
    m_currentTpl->offsetCheck = ui->radioButton_offset->isChecked();
    m_currentTpl->offset = ui->doubleSpinBox_offset->value();

    m_currentTpl->CheckGeneratorOutput = ui->ch_GeneratorOutput->isChecked(); //发生器输出
    m_currentTpl->GeneratorOutputYmax = ui->doubleSpinBox_Gmax->value();
    m_currentTpl->GeneratorOutputYmin = ui->doubleSpinBox_Gmin->value();
    m_currentTpl->GeneratorOutputXAxisScale = static_cast<AxisScale>(ui->co_GeneratorXmodel->currentIndex());
    m_currentTpl->GeneratorOutputYAxisScale = static_cast<AxisScale>(ui->co_GeneratorYmodel->currentIndex());
    m_currentTpl->CheckAmplifierFP = ui->ch_AmplifierFP->isChecked(); //功放前向功率
    m_currentTpl->AmplifierFPYmax = ui->doubleSpinBox_AFmax->value();
    m_currentTpl->AmplifierFPYmin = ui->doubleSpinBox_AFmin->value();
    m_currentTpl->AmplifierFPXAxisScale = static_cast<AxisScale>(ui->co_AmplifierFPXmodel->currentIndex());
    m_currentTpl->AmplifierFPYAxisScale = static_cast<AxisScale>(ui->co_AmplifierFPYmodel->currentIndex());
    m_currentTpl->CheckAmplifierRP = ui->ch_AmplifierRP->isChecked(); //功放反向功率
    m_currentTpl->AmplifierRPYmax = ui->doubleSpinBox_ARmax->value();
    m_currentTpl->AmplifierRPYmin = ui->doubleSpinBox_ARmin->value();
    m_currentTpl->AmplifierRPXAxisScale = static_cast<AxisScale>(ui->co_AmplifierRPXmodel->currentIndex());
    m_currentTpl->AmplifierRPYAxisScale = static_cast<AxisScale>(ui->co_AmplifierRPYmodel->currentIndex());
    m_currentTpl->CheckVSWR = ui->ch_VSWR->isChecked(); //驻波比
    m_currentTpl->VSWRYmax = ui->doubleSpinBox_Smax->value();
    m_currentTpl->VSWRYmin = ui->doubleSpinBox_Smin->value();
    m_currentTpl->VSWRXAxisScale = static_cast<AxisScale>(ui->co_VSWRXmodel->currentIndex());
    m_currentTpl->VSWRYAxisScale = static_cast<AxisScale>(ui->co_VSWRYmodel->currentIndex());
    m_currentTpl->CheckImmunityLevel = ui->ch_ImmunityLevel->isChecked(); //抗干扰电平
    m_currentTpl->ImmunityLevelYmax = ui->doubleSpinBox_Imax->value();
    m_currentTpl->ImmunityLevelYmin = ui->doubleSpinBox_Imin->value();
    m_currentTpl->ImmunityLevelXAxisScale = static_cast<AxisScale>(ui->co_ImmunityLevelXmodel->currentIndex());
    m_currentTpl->ImmunityLevelYAxisScale = static_cast<AxisScale>(ui->co_ImmunityLevelYmodel->currentIndex());

    //校验每个子区间的关键字段（避免外键失败、数据越界等）
    QVector<int> invalidRows;
    for (int i = 0; i < m_currentTpl->subBands.size(); ++i) {
        const auto &sbp = m_currentTpl->subBands[i];
        if (!sbp)
            continue;

        // 校验硬件模板
        if (sbp->hardwareTemplateID <= 0) {
            invalidRows.push_back(i);
        }

        // 可选：更多校验（起止频率、步长等）
        if (sbp->startFreq <= 0 || sbp->stopFreq <= 0 || sbp->stopFreq <= sbp->startFreq)
            invalidRows.push_back(i);
    }
    if (!invalidRows.isEmpty()) {
        const int r = invalidRows.front();
        ui->tableView->setCurrentIndex(m_subModel->index(r, 0));
        QMessageBox::warning(this, tr("未选择硬件模板"),
                             tr("第 %1 行子区间未选择硬件模板，无法保存。\n请选择硬件模板。").arg(r + 1));
        return;
    }

    //保存（DataManager 内部将根据 id 决定 insert 或 update）
    const bool ok = DataManager::instance()->updateTestTemplate(m_currentTpl);

    //成功后，刷新概览名称与当前模板（更新子区间ID，尤其是 update 时你是删除重插）
    if (ok) {
        // 更新并行数组 m_overviews 的名字
        if (listIdx.isValid()) {
            const int row = listIdx.row();
            if (row >= 0 && row < m_overviews.size())
                m_overviews[row].name = m_currentTpl->name;

            // 保证列表显示的文字与对象一致
            m_modelTemplateList->setData(listIdx, m_currentTpl->name);
        }

        // 重新加载当前模板，保证拿到最新的子区间 ID（尤其 update 时）
        TestTemplatePtr reloaded = DataManager::instance()->getFullTestTemplate(m_currentTpl->id);
        if (reloaded) {
            m_currentTpl = reloaded;
            m_subModel->setSubBands(m_currentTpl->subBands);

            // 若希望保持当前选中行
            if (curRowIdx.isValid() && curRowIdx.row() < m_subModel->rowCount()) {
                const QModelIndex keep = m_subModel->index(curRowIdx.row(), 0);
                ui->tableView->setCurrentIndex(keep);
            } else if (m_subModel->rowCount() > 0) {
                ui->tableView->setCurrentIndex(m_subModel->index(0, 0));
            }
        }
    }

    QMessageBox::information(this, ok ? tr("成功") : tr("失败"),
                             ok ? tr("测试模板已保存。") : tr("保存失败，请检查日志。"));
}

/**
 * @brief TestTemplateWidget::on_tBtn_synchronize_clicked
 * @details 将当前场强值同步应用到全部子区间。
 */
void TestTemplateWidget::on_tBtn_synchronize_clicked()
{
    //检查前提条件
    if (!m_currentTpl || m_currentTpl->subBands.isEmpty()) {
        return;
    }

    // 获取源数据
    const double syncValue = ui->doubleSpinBox_immunityValue->value();

    // 屏蔽信号，防止在循环中频繁触发 onEditorChanged
    QScopedValueRollback<bool> guard(m_blockEditorSignals, true);

    // 遍历并修改数据模型
    for (const auto &subBandPtr : m_currentTpl->subBands) {
        if (subBandPtr) {
            subBandPtr->immunityLevelType = ImmunityLevelType::Fixed; // 强制设置为“固定值”模式
            subBandPtr->immunityLevelValue = syncValue;               // 应用新的场强值
        }
    }

    m_subModel->setSubBands(m_currentTpl->subBands);
    QModelIndex currentIndex = ui->tableView->currentIndex();
    if (currentIndex.isValid()) {
        loadRowToEditors(currentIndex.row());
    }
}

/**
 * @brief TestTemplateWidget::on_cBox_measurementCategory_currentIndexChanged
 * @details 处理测量类别切换并调整界面。
 * @param index 下拉框索引。
 */
void TestTemplateWidget::on_cBox_measurementCategory_currentIndexChanged(int index)
{
    HardwareTemplateType selectedType = static_cast<HardwareTemplateType>(index);
    refreshHwTemplateCommbox(selectedType);

    if (HardwareTemplateType::RS == selectedType) {
        ui->cBox_levelunit->setCurrentText(STR_UNIT_VM);
        ui->radioButton_offset->hide();
        ui->doubleSpinBox_offset->hide();
        ui->label_offsetUnit->hide();
    } else {
        ui->cBox_levelunit->setCurrentText("dB\u03BCA");
        bool isSensor = (LevelModeType::Sensor == static_cast<LevelModeType>(ui->cBox_levelmode->currentData().toInt())) ? true : false;
        ui->radioButton_offset->setVisible(isSensor);
        ui->doubleSpinBox_offset->setVisible(isSensor);
        ui->label_offsetUnit->setVisible(isSensor);
    }
}

/**
 * @brief TestTemplateWidget::on_cBox_levelmode_currentIndexChanged
 * @details 根据功率调平模式调整偏置输入的可见性。
 * @param index 下拉框索引。
 */
void TestTemplateWidget::on_cBox_levelmode_currentIndexChanged(int index)
{
    if (HardwareTemplateType::CS == static_cast<HardwareTemplateType>(ui->cBox_measurementCategory->currentData().toInt())) {
        bool isSensor = (LevelModeType::Sensor == static_cast<LevelModeType>(index)) ? true : false;
        ui->radioButton_offset->setVisible(isSensor);
        ui->doubleSpinBox_offset->setVisible(isSensor);
        ui->label_offsetUnit->setVisible(isSensor);
    }
}
